package com.gitee.grassprogramming.orm.base;


import com.gitee.grassprogramming.orm.design.BaseEntity;
import com.gitee.grassprogramming.orm.design.OptionType;
import com.gitee.grassprogramming.orm.util.MapperUtil;
import com.gitee.grassprogramming.orm.util.SQLBuilder;
import com.mysql.jdbc.StringUtils;

import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by paul on 2019/1/1.
 */
public class PreCommand {
    private Command command;
    private SQLBuilder sqlBuilder;
    private MapperUtil mapperUtil;

    public PreCommand(){
        sqlBuilder = new SQLBuilder();
        mapperUtil = new MapperUtil();
    }

    public <T extends BaseEntity> Command initInsert(T entity) throws Exception{
        String sql = sqlBuilder.Build(entity, OptionType.insert);
        ArrayList<Object> params = new  ArrayList<Object>();
        List<Field> fs = mapperUtil.GetMapperFields(entity);
        for(Field f :fs){
            params.add(f.get(entity));
        }
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initDelete(T entity) throws Exception{
        String sql = sqlBuilder.Build(entity, OptionType.delete);
        ArrayList<Object> params = new  ArrayList<Object>();
        String keyfieldvalue = mapperUtil.GetKeyFieldValue(entity);
        params.add(keyfieldvalue);
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initUpdate(T entity) throws Exception{
        String sql = sqlBuilder.Build(entity, OptionType.update);
        ArrayList<Object> params = new  ArrayList<Object>();
        List<Field> fs = mapperUtil.GetMapperFields(entity);
        String keyFieldName = mapperUtil.GetKeyFieldName(entity.getClass());
        String keyFieldGuid = "";
        for(Field f :fs){
            if(f.getName().equals(keyFieldName)){
                keyFieldGuid = f.get(entity).toString();
            }
            params.add(f.get(entity));
        }
        //where 条件主键参数
        params.add(keyFieldGuid);
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initUpdate(Object entity,Class<T> tClass) throws Exception{
        StringBuilder sql = new StringBuilder();
        ArrayList<Object> params = new  ArrayList<Object>();
        List<Field> entityfs = mapperUtil.GetMapperFields(entity);
        List<Field> classfs = mapperUtil.GetMapperFields(tClass);
        List<Field> updatefs = new ArrayList<Field>();
        String keyFieldName = mapperUtil.GetKeyFieldName(tClass);
        String keyFieldGuid = "";
        //先对比传入的entity有多少字段是tclass类型所包含的
        for(Field f :entityfs){
           for(int i=0;i<classfs.size();i++){
               if(f.getName().equals(classfs.get(i).getName())){
                   updatefs.add(f);
                   break;
               }
           }
           if(f.getName()==keyFieldName){
               keyFieldGuid = String.valueOf(f.get(entity));
           }
        }
        //拼接sql
        if(StringUtils.isNullOrEmpty(keyFieldGuid)){
            throw  new RuntimeException("entity do not contains the keyfield of classtype");
        }else{
            String tablename = mapperUtil.GetTableName(tClass);
            String KeyFieldName = mapperUtil.GetKeyFieldName(tClass);
            sql.append(MessageFormat.format("update  {0} set ", tablename));
            for (Field f : updatefs) {
                if (updatefs.indexOf(f) == updatefs.size() - 1) {
                    sql.append(MessageFormat.format(" {0}=?",f.getName()));
                }else{
                    sql.append(MessageFormat.format(" {0}=?,",f.getName()));
                }
                params.add(f.get(entity));
            }
            sql.append(MessageFormat.format(" where {0}=?",KeyFieldName));
        }
        //where 条件主键参数
        params.add(keyFieldGuid);
        command = CommandFactory.getCommand();
        command.setSQLText(sql.toString());
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initCount(Class<T> tClass) throws Exception{
        String sql = sqlBuilder.Build(tClass,OptionType.count);
        ArrayList<Object> params = new  ArrayList<Object>();
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initFindOne(String keyGuid, Class<T> tClass) throws Exception{
        String sql = sqlBuilder.Build(tClass,OptionType.findList);
        ArrayList<Object> params = new  ArrayList<Object>();
        params.add(keyGuid);
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initFindOne(String KeyName,String keyGuid, Class<T> tClass) throws Exception{
        String sql = sqlBuilder.Build(tClass,KeyName,OptionType.findList);
        ArrayList<Object> params = new  ArrayList<Object>();
        params.add(keyGuid);
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initFindList(String columns, String where,Object[] args,String orderBy,Class<T> tClass) throws Exception{
        String sql = sqlBuilder.Build(tClass,OptionType.findList,columns,where,orderBy);
        ArrayList<Object> params = new  ArrayList<Object>();
        if(null!=args){
            for (Object obj:args) {
                params.add(obj);
            }
        }
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public <T extends BaseEntity> Command initFindPage(String columns, String where,Object[] args,String orderBy,int pageIndex,int pageSize,Class<T> tClass) throws Exception{
        String sql = sqlBuilder.Build(tClass,OptionType.findPage,columns,where,orderBy,pageIndex,pageSize);
        ArrayList<Object> params = new  ArrayList<Object>();
        if(null!=args){
            for (Object obj:args) {
                params.add(obj);
            }
        }
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public Command initFindView(String viewName,String columns, String where,Object[] args,String orderBy) throws Exception{
        String sql = sqlBuilder.Build(viewName,columns,where,orderBy);
        ArrayList<Object> params = new  ArrayList<Object>();
        if(null!=args){
            for (Object obj:args) {
                params.add(obj);
            }
        }
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public Command initFindViewPage(String viewName,String columns, String where,Object[] args,String orderBy,int pageIndex,int pageSize) throws Exception{
        String sql = sqlBuilder.Build(viewName,columns,where,orderBy,pageIndex,pageSize);
        ArrayList<Object> params = new  ArrayList<Object>();
        if(null!=args){
            for (Object obj:args) {
                params.add(obj);
            }
        }
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }

    public Command initExecuteSQL(String sql,Object[] args){
        ArrayList<Object> params = new  ArrayList<Object>();
        if(null!=args){
            for (Object obj:args) {
                params.add(obj);
            }
        }
        command = CommandFactory.getCommand();
        command.setSQLText(sql);
        command.setSQLParams(params);
        return command;
    }
}
